import React, {CanvasHTMLAttributes, useEffect, useRef, useState} from 'react';
import './index.scss';

interface IPieChartOfBlockingAlarms {
  downstreamJam?: number;
  indexorStop?: number;
  blackImage?: number;
  emergencyStop?: number;
  temperature?: number;
  rejectControlError?: number;
}

// 按钮参数类型
type drawButtonPropsType = {
  width: number;
  color: string;
  x: number;
  y: number;
  height: number;
  radius: number;
  text: string;
  delay: number;
  fontSize: number;
  ctx: CanvasRenderingContext2D;
};
//箭头参数类型
type drawArrowPropsType = {
  fromX: number;
  fromY: number;
  toX: number;
  toY: number;
  theta: number;
  headlen: number;
  width: number;
  color: string;
  ctx: CanvasRenderingContext2D;
};

//左下角箭头类型
type drawBreakArrowType = {
  centerX: number
  centerY: number
  x: number
  y: number
  toX: number
  toY: number
  width: number
  r: number
  theta: number
  headlen: number
  startAngle?: number
  endAngle?: number
  counterclockwise: boolean
  ctx: CanvasRenderingContext2D;
}

// 绘制整个图的方法
const drawPartOfPieChart = (
  ctx: CanvasRenderingContext2D,
  radius: number,
  dataArr: number[],
  colorArr: string[],
  textArr: string[]
) => {
  //format data, use %
  let totalNumber = 0;
  const newDataArr: number[] = [];
  for (let i = 0; i < dataArr.length; i++) {
    totalNumber += dataArr[i];
  }
  for (let i = 0; i < dataArr.length; i++) {
    newDataArr.push(dataArr[i] / totalNumber);
  }
  // start degree
  let startAngle = 0;
  // end degree
  let endAngle = 0;
  // circle center
  const ox = radius * 1.8;
  const oy = radius * 1.5;
  for (let i = 0; i < dataArr.length; i++) {
    // moved angle
    const angle = newDataArr[i] * Math.PI * 2;
    endAngle = endAngle + angle;
    ctx.beginPath();
    //move to circle center
    ctx.moveTo(ox, oy);
    // draw each part
    ctx.arc(ox, oy, radius, startAngle, endAngle, false);
    ctx.closePath();
    ctx.fillStyle = colorArr[i];
    ctx.fill();
    // change start angle
    startAngle = endAngle;
    if (i === dataArr.length - 1) {
      startAngle = 0;
      endAngle = 0;
    }
  }
  // 图例
  const legendLength = 10;
  const posX = radius * 3.5;
  for (let j = 0; j < dataArr.length; j++) {
    const number = 30 * (j + 2);
    ctx.fillStyle = colorArr[j];
    // icon
    ctx.fillRect(posX, number, legendLength, legendLength);
    ctx.moveTo(posX, number);
    ctx.font =
      "bold 16px 'Roboto', Serif, Sans-serif, cursive, fantasy, Monospace";
    const words = `${textArr[j]}`;
    ctx.fillStyle = '#bac4c5';
    // words
    ctx.fillText(words, posX + legendLength + 5, number + legendLength + 1);
  }
  //折线和文字
  let lineStartAngle = 0;
  // broken line length
  const brokenLine = 10;
  // text length
  const textLength = brokenLine * 4;
  for (let i = 0; i < dataArr.length; i++) {
    // moved angle
    const angle = newDataArr[i] * Math.PI * 2;
    endAngle = endAngle + angle;
    // brokenLine
    const newAngle = angle / 2;
    const brokenAngle = lineStartAngle + newAngle;
    lineStartAngle += angle;
    // line
    const distancex = Math.cos(brokenAngle);
    const distancey = Math.sin(brokenAngle);
    const startx = radius * distancex;
    const starty = radius * distancey;
    const endx = (radius + brokenLine) * distancex;
    const endy = (radius + brokenLine) * distancey;
    // intersection of start point of broken line and the circle
    const beginx = ox + startx;
    const beginy = oy + starty;
    // intersection of end point of broken line and the circle
    const overx = ox + endx;
    const overy = oy + endy;
    ctx.beginPath();
    ctx.moveTo(beginx, beginy);
    ctx.lineTo(overx, overy);
    const percent = `${Math.round(100 * newDataArr[i])}%`;
    let overlinex = overx + textLength;
    let percentX = overx + 15;
    if (overx <= ox) {
      overlinex = overx - textLength;
      percentX = overlinex;
    }
    ctx.lineTo(overlinex, overy);
    ctx.strokeStyle = colorArr[i];
    ctx.stroke();
    ctx.font =
      "500 16px 'Roboto', Serif, Sans-serif, cursive, fantasy, Monospace";
    ctx.fillStyle = colorArr[i];
    ctx.fillText(percent, percentX, overy - 2);
  }
};

const buttonTopStartY = 10;
const buttonStartX = 300;
const buttonBottomStartY = 10;
const buttonHeight = 40;
const buttonWidth = 100;
const buttonRadius = 20;
const buttonFontSize = 14;
const buttonMargin = 10;
const buttonDescMarginTop = 40;
const buttonDescColor = '#4e5969';
const buttonDescFontSize = 12;
const buttonBottomX = 110

enum ButtonType {
  ServerDrawDelay,
  ServerEncodeDelay,
  TransmissionDelay,
  ClientEncodeDelay,
  ClientDrawDelay,
  UploadingDelay
}
let buttonList = [
  {
    type: ButtonType.ServerDrawDelay,
    text: '服务器渲染时延',
    delay: 0
  },
  {
    type: ButtonType.ServerEncodeDelay,
    text: '编码时延',
    delay: 0
  },
  {
    type: ButtonType.TransmissionDelay,
    text: '传输时延',
    delay: 0
  },
  {
    type: ButtonType.ClientEncodeDelay,
    text: '终端解码时延',
    delay: 0
  },
  {
    type: ButtonType.ClientDrawDelay,
    text: '终端渲染时延',
    delay: 0
  },
  {
    type: ButtonType.UploadingDelay,
    text: '指令上传时延',
    delay: 0
  }
];

//画按钮
function drawButton({
  color,
  x,
  y,
  width,
  height,
  radius,
  text,
  fontSize,
  delay,
  ctx
}: drawButtonPropsType) {
  //x/y:按钮起始点,width/height按钮宽高,radius弧度
  //分为4条直线4个圆角绘制
  ctx.beginPath();
  ctx.fillStyle = color;
  ctx.moveTo(x + radius, y);
  ctx.lineTo(x + width - radius, y);
  ctx.arc(
    x + width - radius,
    y + radius,
    radius,
    (Math.PI * 3) / 2,
    Math.PI * 2
  );
  ctx.lineTo(x + width, y + height - radius);
  ctx.arc(
    x + width - radius,
    y + height - radius,
    radius,
    Math.PI,
    Math.PI / 2
  );
  ctx.lineTo(x + radius, y + height);
  ctx.arc(x + radius, y + height - radius, radius, Math.PI / 2, Math.PI);
  ctx.lineTo(x, y + radius);
  ctx.arc(x + radius, y + radius, radius, Math.PI, (Math.PI * 3) / 2);
  ctx.fill();
  ctx.closePath();

  ctx.beginPath();
  ctx.fillStyle = '#fff';
  ctx.font = fontSize + 'px 黑体';
  ctx.textAlign = 'center';
  ctx.textBaseline = 'middle';
  ctx.fillText(text, x + width / 2, y + height / 2);
}

// 画箭头
function drawArrow({
  fromX,
  fromY,
  toX,
  toY,
  theta,
  headlen,
  width,
  color,
  ctx
}: drawArrowPropsType) {
  theta = typeof theta != 'undefined' ? theta : 30;
  headlen = typeof theta != 'undefined' ? headlen : 10;
  width = typeof width != 'undefined' ? width : 1;
  color = typeof color != 'undefined' ? color : '#000';

  var angle = (Math.atan2(fromY - toY, fromX - toX) * 180) / Math.PI,
    angle1 = ((angle + theta) * Math.PI) / 180,
    angle2 = ((angle - theta) * Math.PI) / 180,
    topX = headlen * Math.cos(angle1),
    topY = headlen * Math.sin(angle1),
    botX = headlen * Math.cos(angle2),
    botY = headlen * Math.sin(angle2);
  if (ctx) {
    ctx.save();
    ctx.beginPath();
    var arrowX = fromX - topX,
      arrowY = fromY - topY;
    ctx.moveTo(arrowX, arrowY);
    ctx.moveTo(fromX, fromY);
    ctx.lineTo(toX, toY);
    arrowX = toX + topX;
    arrowY = toY + topY;
    ctx.moveTo(arrowX, arrowY);
    ctx.lineTo(toX, toY);
    arrowX = toX + botX;
    arrowY = toY + botY;
    ctx.lineTo(arrowX, arrowY);
    ctx.strokeStyle = color;
    ctx.lineWidth = width;
    ctx.stroke();
    ctx.restore();
  }
}

//画右上的按钮
function drawBreakBottomRightArrow({
  centerX,
  centerY,
  x,
  y,
  toX,
  toY,
  width,
  r,
  theta,
  headlen,
  startAngle,
  endAngle,
  counterclockwise,
  ctx
}: drawBreakArrowType) {
  const pi = Math.PI
  if (ctx) {
    ctx.beginPath()
    ctx.moveTo(centerX + r, toY + r)
    ctx.lineTo(centerX + r, y)
    ctx.arc(
      centerX,
      centerY + r,
      r,
      startAngle ? startAngle : 0,
      endAngle ? endAngle : pi * 1.5,
      counterclockwise,
    )

    var angle = (Math.atan2(centerY - toY, centerX - toX) * 180) / Math.PI,
      angle1 = ((angle + theta) * Math.PI) / 180,
      angle2 = ((angle - theta) * Math.PI) / 180,
      topX = headlen * Math.cos(angle1),
      topY = headlen * Math.sin(angle1),
      botX = headlen * Math.cos(angle2),
      botY = headlen * Math.sin(angle2)

    var arrowX = toX + topX,
      arrowY = toY + topY
    ctx.moveTo(arrowX, arrowY)
    ctx.lineTo(toX, toY)
    arrowX = toX + botX
    arrowY = toY + botY
    ctx.lineTo(arrowX, arrowY)
    ctx.moveTo(centerX, centerY)
    ctx.lineTo(toX, centerY)
    ctx.strokeStyle = '#1861ce'
    ctx.lineWidth = width
    ctx.stroke()
    ctx.closePath()
  }
}

//画左下的按钮
function drawBreakLeftDownArrow({
  centerX,
  centerY,
  x,
  y,
  toX,
  toY,
  width,
  r,
  theta,
  headlen,
  startAngle,
  endAngle,
  counterclockwise,
  ctx
}: drawBreakArrowType) {
  const pi = Math.PI
  if (ctx) {
    ctx.beginPath()

    //竖
    // ctx.moveTo(centerX - r, y + r)
    // ctx.lineTo(centerX - r, toY)
    ctx.moveTo(centerX, y + r)
    ctx.lineTo(centerX, toY)

    ctx.arc(
      centerX + r,
      centerY + r,
      r,
      startAngle ? startAngle : 0,
      endAngle ? endAngle : pi * 1.5,
      counterclockwise,
    )

    var angle = (Math.atan2(centerY - toY, centerX - toX) * 180) / Math.PI,
      angle1 = ((angle + theta) * Math.PI) / 180,
      angle2 = ((angle - theta) * Math.PI) / 180,
      topX = headlen * Math.cos(angle1),
      topY = headlen * Math.sin(angle1),
      botX = headlen * Math.cos(angle2),
      botY = headlen * Math.sin(angle2)

    var arrowX = toX + topX,
      arrowY = toY + topY
    ctx.moveTo(arrowX, arrowY)
    ctx.lineTo(toX, toY)
    arrowX = toX + botX
    arrowY = toY + botY
    ctx.lineTo(arrowX, arrowY)

    //横
    ctx.moveTo(centerX + r, centerY)
    ctx.lineTo(x, centerY)

    ctx.strokeStyle = '#1861ce'
    ctx.lineWidth = width
    ctx.stroke()
    ctx.closePath()
  }
}

// pie的相关数据
const PieMap = () => {
  // drawPieChartOfBlockingAlarms(pieChartOfBlockingAlarms: IPieChartOfBlockingAlarms) {
  function drawPieChartOfBlockingAlarms(
    pieChartOfBlockingAlarms: IPieChartOfBlockingAlarms | any
  ) {
    const dataArr: number[] = [];
    const textArr: string[] = [];
    for (const key in pieChartOfBlockingAlarms) {
      /** get each part value of pie chart then add it in dataArr */
      dataArr.push(pieChartOfBlockingAlarms[key]);
      textArr.push(key);
    }
    //每个部分对应的颜色
    const colorArr = [
      '#2980b9',
      '#16a085',
      '#9bbb59',
      '#f39c12',
      '#c0392b',
      '#4b2c50'
    ];
    // ts 获取dom对象同时使用断言 否则会报错
    const canvasElement: HTMLCanvasElement = document.getElementById(
      'tes-dashbaords-pieChart-blockingAlarms'
    ) as HTMLCanvasElement;
    const ctx: CanvasRenderingContext2D = canvasElement.getContext(
      '2d'
    ) as CanvasRenderingContext2D;
    //半径
    const radius = canvasElement.height / 3;
    drawPartOfPieChart(ctx, radius, dataArr, colorArr, textArr);
  }


  //利用 canvas 画按钮
  function ButtonMap() {
    const canvasElement: HTMLCanvasElement = document.getElementById(
      'test-canvas-button'
    ) as HTMLCanvasElement;
    const ctx: CanvasRenderingContext2D = canvasElement.getContext(
      '2d'
    ) as CanvasRenderingContext2D;
    drawButton({
      color: '#1861ce',
      x: buttonStartX, // Align the second one
      y: buttonTopStartY,
      delay: 20,
      width: buttonWidth,
      height: buttonHeight,
      radius: buttonRadius,
      text: '我的按钮',
      fontSize: buttonFontSize,
      ctx
    });
    drawArrow({
      fromX: buttonStartX+buttonWidth*2,
      fromY: buttonBottomStartY+buttonHeight/2,
      toX: buttonStartX+buttonWidth,
      toY: buttonBottomStartY+buttonHeight/2,
      theta: 30,
      headlen: 15,
      width: 3,
      color: '#1861ce',
      ctx
    });
    drawButton({
      color: '#1861ce',
      x: buttonStartX+buttonWidth*2, // Align the second one
      y: buttonTopStartY,
      delay: 20,
      width: buttonWidth,
      height: buttonHeight,
      radius: buttonRadius,
      text: '我的按钮',
      fontSize: buttonFontSize,
      ctx
    });
    drawBreakBottomRightArrow({
      centerX: buttonStartX + (buttonMargin + buttonWidth) * 5 - 100 , //控制横的长度
      centerY: buttonTopStartY + buttonHeight / 2, //控制 横竖整体高度
      x: buttonStartX + (buttonMargin + buttonWidth) * 5 -100,  //控制横的长度
      y: buttonBottomStartY+200, // 控制 竖的长度
      toX: buttonStartX+buttonWidth*3, // 控制起点 x
      toY: buttonTopStartY + buttonHeight / 2, // 控制起点 y
      width: 3,
      r: 10,
      theta: 30,
      headlen: 15,
      counterclockwise: true,
      ctx
    })
    let pi = Math.PI
    drawBreakLeftDownArrow({
      centerX: buttonStartX - buttonMargin - 130 , //控制横的长度
      centerY: buttonTopStartY + buttonHeight / 2 ,
      x: buttonStartX,
      y: buttonHeight / 2 + 10,
      toX: buttonStartX - buttonMargin - 130, //
      toY: buttonBottomStartY + buttonHeight / 2 + 180, // 控制 竖的长度
      width: 3,
      r: 10,
      theta: 30,
      headlen: 15,
      startAngle: pi,
      endAngle: 1.5 * pi,
      counterclockwise: false,
      ctx
    })

    drawButton({
      color: '#1861ce',
      // buttonStartX =300
      x: buttonBottomX, // Align the second one
      y: buttonTopStartY + buttonHeight / 2 + 180,
      delay: 20,
      width: buttonWidth,
      height: buttonHeight,
      radius: buttonRadius,
      text: '我的按钮',
      fontSize: buttonFontSize,
      ctx
    });
    drawArrow({
      fromX: (buttonBottomX +buttonWidth),//从哪个x点
      fromY: buttonBottomStartY+buttonHeight+180 ,//从哪个y点
      toX: buttonStartX,//到哪个x点
      toY: buttonBottomStartY+buttonHeight +180,//到哪个y点
      theta: 30,
      headlen: 15,
      width: 3,
      color: '#1861ce',
      ctx
    });
    drawButton({
      color: '#1861ce',
      x: buttonBottomX +buttonWidth+90, // Align the second one
      y: buttonTopStartY + buttonHeight / 2 + 180,
      delay: 20,
      width: buttonWidth,
      height: buttonHeight,
      radius: buttonRadius,
      text: '我的按钮',
      fontSize: buttonFontSize,
      ctx
    });
    drawArrow({
      fromX: buttonStartX+buttonWidth,//从哪个x点
      fromY: buttonBottomStartY+buttonHeight+180 ,//从哪个y点
      toX: 2*buttonStartX-buttonWidth,//到哪个x点
      toY: buttonBottomStartY+buttonHeight +180,//到哪个y点
      theta: 30,
      headlen: 15,
      width: 3,
      color: '#1861ce',
      ctx
    });
    drawButton({
      color: '#1861ce',
      x: 2*buttonStartX-buttonWidth, // Align the second one
      y: buttonTopStartY + buttonHeight / 2 + 180,
      delay: 20,
      width: buttonWidth,
      height: buttonHeight,
      radius: buttonRadius,
      text: '我的按钮',
      fontSize: buttonFontSize,
      ctx
    });
    drawArrow({
      fromX: 2*buttonStartX,//从哪个x点
      fromY: buttonBottomStartY+buttonHeight+180 ,//从哪个y点
      toX: 2*buttonStartX+buttonWidth,//到哪个x点
      toY: buttonBottomStartY+buttonHeight +180,//到哪个y点
      theta: 30,
      headlen: 15,
      width: 3,
      color: '#1861ce',
      ctx
    });
    drawButton({
      color: '#1861ce',
      x: 2*buttonStartX+buttonWidth, // Align the second one
      y: buttonTopStartY + buttonHeight / 2 + 180,
      delay: 20,
      width: buttonWidth,
      height: buttonHeight,
      radius: buttonRadius,
      text: '我的按钮',
      fontSize: buttonFontSize,
      ctx
    });
  }
  useEffect(() => {
    drawPieChartOfBlockingAlarms({
      downstreamJam: 20,
      indexorStop: 5,
      blackImage: 6,
      temperature: 18,
      rejectControlError: 20
    });

    // 初始挂载
    ButtonMap();
  }, []);

  return (
    <div>
      <canvas
        width={1000}
        height={300}
        id="tes-dashbaords-pieChart-blockingAlarms"
      ></canvas>
      <canvas width={500 * 2} height={400} id="test-canvas-button"></canvas>
    </div>
  );
};

export default PieMap;
